package come.bjpowernode.javase.threadsafe2;
/*
银行账户。
    使用线程同步机制，解决线程安全问题。
 */
public class Account {
    //账号
    private String actno;
    //余额
    private double balance;

    Object obj1 = new Object();

    public Account() {
    }

    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
    //取款方法
    public void  withdraw(double money){
        //以下这几行代码必须是线程排队的，不能并发
        //一个线程把这里的diamante全部执行结束之后，另一个线程才能进来
        /*
        线程同步机制的语法：
            synchronized(){
                线程同步代码块
            }
            synchronized后面的小括号中传的这个“数据”是相当重要的
            这个数据必须是多线程共享的数据，才能达到多线程排队的效果。

            ()中写什么
                假设t1，t2，t3，t4，t5有五个线程
                你只希望t1、t3，t2排队。
                你一定要在()写一个t1、2、3共享的对象，而这个对象对t4、5不是共享的。

            这里的共享对象是账户对象，写this即可。
            但，不一定是this，只要是多线程共享的对象即可。

            在java语言中任何对象都有一把锁，这个锁就是一个标记，只是叫做锁，
            100个对象100把锁。
         */
        Object obj2 = new Object();
        //synchronized(actno){//安全
        //synchronized(this){//安全
        //synchronized(obj1){//安全
        //synchronized(null){//异常，空指针异常
        synchronized("abc"){//安全,"abc"在常量池中，只有一个。
        //synchronized(obj2){//不安全,因为obj2是局部变量，
            // 每一个线程访问都会创建一个obj2，因此obj2不是共享对象.

            double before = this.balance;
            double after = before - money;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);

        }

    }
}
